using System;
using System.Collections.Generic;
using System.Collections;
using System.Text;
using System.Reflection;

public class MethodDefinition {
	
	private String className;
	private String methodName;

    private System.Collections.Hashtable parametersDefinition = new Hashtable();
	private ParameterType returnType;

    private System.Collections.Hashtable integerParameter = new Hashtable();
    private System.Collections.Hashtable doubleParameter = new Hashtable();
    private System.Collections.Hashtable stringParameter = new Hashtable();
	
	private String returnString;
	private int returnInteger;
	private Double returnDouble;
	
	public MethodDefinition() {
	}

    public void setClassName(String name){
		this.className = name;
	}
	
	public void setMethodName(String name){
		this.methodName = name;
	}
	
	public void setMethodReturnType(ParameterType returnType){
		this.returnType = returnType;
	}
	
	public void addParameter(String parameter, int position){
		this.parametersDefinition.Add(position, ParameterType.PARAMETER_STRING);
        this.stringParameter.Add(position, parameter);
	}
	
	public void addParameter(int parameter, int position){
        this.parametersDefinition.Add(position, ParameterType.PARAMETER_INTEGER);
        this.integerParameter.Add(position, parameter);
	}
	
	public void addParameter(Double parameter, int position){
        this.parametersDefinition.Add(position, ParameterType.PARAMETER_DOUBLE);
        this.doubleParameter.Add(position, parameter);
	}
	
	public void callMethod()
    {
        if (this.className == null || this.methodName == null)
        {
            throw new InvalidOperationException("Class or method name not configured");
        }
        else
        {
            int numParameters = this.parametersDefinition.Count;
            ParameterType[] parameterTypeArray = new ParameterType[numParameters];
            Object[] parameterArray = new Object[numParameters];

            for (int i = 0; i < numParameters; i++)
            {
                ParameterType parType = (ParameterType)this.parametersDefinition[i];

                switch (parType)
                {
                    case ParameterType.PARAMETER_DOUBLE:
                        parameterTypeArray[i] = ParameterType.PARAMETER_DOUBLE;
                        parameterArray[i] = this.doubleParameter[i];
                        break;
                    case ParameterType.PARAMETER_INTEGER:
                        parameterTypeArray[i] = ParameterType.PARAMETER_INTEGER;
                        parameterArray[i] = this.integerParameter[i];
                        break;
                    case ParameterType.PARAMETER_STRING:
                        parameterTypeArray[i] = ParameterType.PARAMETER_STRING;
                        parameterArray[i] = this.stringParameter[i];
                        break;
                    default:
                        throw new InvalidOperationException("");
                }
            }

            Object obj = DomainModel.getInstance().getDomainModelObject(this.className);
            MethodInfo method = obj.GetType().GetMethod(this.methodName);

            

            Object returnValue = method.Invoke(obj, parameterArray);

            switch (this.returnType)
            {
                case ParameterType.PARAMETER_DOUBLE:
                    this.returnDouble = (Double)returnValue;
                    break;
                case ParameterType.PARAMETER_INTEGER:
                    this.returnInteger = (int)returnValue;
                    break;
                case ParameterType.PARAMETER_STRING:
                    this.returnString = (String)returnValue;
                    break;
                default:
                    throw new InvalidOperationException("");
            }
        }
    }
	
	public int getIntegerReturnValue()
    {
		
		if (this.returnType.CompareTo(ParameterType.PARAMETER_INTEGER) == 0){
			return this.returnInteger;
		}else{
			throw new InvalidOperationException("Invalid method return type");
		}
	}
	
	public String getStringReturnValue()
    {

        if (this.returnType.CompareTo(ParameterType.PARAMETER_STRING) == 0)
        {
			return this.returnString;
		}else{
			throw new InvalidOperationException("Invalid method return type");
		}
	}
	
	public Double getDoubleReturnValue()
    {

        if (this.returnType.CompareTo(ParameterType.PARAMETER_DOUBLE) == 0)
        {
			return this.returnDouble;
		}else{
            throw new InvalidOperationException("Invalid method return type");
		}
	}

}


